// 应用完整性检查服务
import CryptoJS from 'crypto-js';
import fs from 'fs';
import path from 'path';

// 应用关键文件列表
const criticalFiles = [
  'main/index.js',
  'preload/index.js',
  'utils/cryptoService.js',
  'utils/authService.js',
  'utils/request.js'
];

// 文件哈希值缓存
let fileHashCache = {};

/**
 * 计算文件的哈希值
 * @param {string} filePath - 文件路径
 * @returns {string} - 文件哈希值
 */
export const calculateFileHash = (filePath) => {
  try {
    const fileContent = fs.readFileSync(filePath, 'utf8');
    return CryptoJS.SHA256(fileContent).toString();
  } catch (error) {
    console.error(`计算文件哈希失败: ${filePath}`, error);
    return '';
  }
};

/**
 * 生成应用文件的哈希清单
 * @param {string} basePath - 应用根目录
 * @returns {Object} - 文件哈希清单
 */
export const generateFileHashes = (basePath) => {
  const hashes = {};
  
  criticalFiles.forEach(file => {
    const fullPath = path.join(basePath, 'src', file);
    hashes[file] = calculateFileHash(fullPath);
  });
  
  return hashes;
};

/**
 * 保存文件哈希清单
 * @param {string} basePath - 应用根目录
 * @param {Object} hashes - 文件哈希清单
 */
export const saveFileHashes = (basePath, hashes) => {
  try {
    const hashesJson = JSON.stringify(hashes, null, 2);
    const hashesPath = path.join(basePath, 'file-hashes.json');
    fs.writeFileSync(hashesPath, hashesJson, 'utf8');
    console.log('文件哈希清单已保存');
  } catch (error) {
    console.error('保存文件哈希清单失败:', error);
  }
};

/**
 * 加载文件哈希清单
 * @param {string} basePath - 应用根目录
 * @returns {Object} - 文件哈希清单
 */
export const loadFileHashes = (basePath) => {
  try {
    const hashesPath = path.join(basePath, 'file-hashes.json');
    if (fs.existsSync(hashesPath)) {
      const hashesJson = fs.readFileSync(hashesPath, 'utf8');
      return JSON.parse(hashesJson);
    }
  } catch (error) {
    console.error('加载文件哈希清单失败:', error);
  }
  return {};
};

/**
 * 验证应用文件完整性
 * @param {string} basePath - 应用根目录
 * @returns {Object} - 验证结果
 */
export const verifyApplicationIntegrity = (basePath) => {
  // 加载存储的哈希值
  const storedHashes = loadFileHashes(basePath);
  if (!storedHashes || Object.keys(storedHashes).length === 0) {
    console.warn('未找到文件哈希清单，无法验证完整性');
    return { valid: false, modifiedFiles: [] };
  }
  
  // 验证文件完整性
  const modifiedFiles = [];
  
  criticalFiles.forEach(file => {
    const fullPath = path.join(basePath, 'src', file);
    const currentHash = calculateFileHash(fullPath);
    const storedHash = storedHashes[file];
    
    if (currentHash !== storedHash) {
      modifiedFiles.push(file);
    }
  });
  
  return {
    valid: modifiedFiles.length === 0,
    modifiedFiles
  };
};

/**
 * 初始化应用完整性检查
 * @param {string} basePath - 应用根目录
 * @param {boolean} forceUpdate - 是否强制更新哈希清单
 * @returns {boolean} - 初始化是否成功
 */
export const initIntegrityCheck = (basePath, forceUpdate = false) => {
  try {
    const hashesPath = path.join(basePath, 'file-hashes.json');
    const hashesExist = fs.existsSync(hashesPath);
    
    if (!hashesExist || forceUpdate) {
      // 生成并保存文件哈希清单
      const hashes = generateFileHashes(basePath);
      saveFileHashes(basePath, hashes);
      fileHashCache = hashes;
      return true;
    }
    
    // 加载现有哈希清单
    fileHashCache = loadFileHashes(basePath);
    return true;
  } catch (error) {
    console.error('初始化完整性检查失败:', error);
    return false;
  }
};

/**
 * 运行时完整性检查
 * @param {string} basePath - 应用根目录
 * @returns {boolean} - 应用是否完整
 */
export const runtimeIntegrityCheck = (basePath) => {
  const result = verifyApplicationIntegrity(basePath);
  
  if (!result.valid) {
    console.error('应用完整性检查失败，检测到以下文件被修改:', result.modifiedFiles);
    return false;
  }
  
  return true;
};